#pragma once

//-----------------------------------------------------------------------------
#pragma warning( disable : 4244 )
#pragma warning( disable : 4251 )
#pragma warning( disable : 4267 )
#pragma warning( disable : 4819 )

//-----------------------------------------------------------------------------
#ifndef _CRT_SECURE_NO_DEPRECATE
#define _CRT_SECURE_NO_DEPRECATE
#endif

//-----------------------------------------------------------------------------
// windows
#ifndef WINVER
#define WINVER 0x0501// xp
#endif
#ifndef _WIN32_WINNT
#define _WIN32_WINNT 0x0501// xp
#endif
#ifndef _WIN32_WINDOWS
#define _WIN32_WINDOWS 0x0410// Windows 98
#endif
#ifndef _WIN32_IE
#define _WIN32_IE 0x0600// IE6.0
#endif
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <windows.h>
#include <tchar.h>
#include <assert.h>

//-----------------------------------------------------------------------------
// stl
#include <string>
#include <vector>
#include <list>
#include <map>
#include <set>
#include<iostream>
#include<sstream>
//-----------------------------------------------------------------------------
inline  static int compareNoCase( const std::string & src, const std::string & est) 
{
	return stricmp( src.c_str(),est.c_str() );
}

//-----------------------------------------------------------------------------
// works like strstr, but is case-insensitive
inline static const char * stristr(const char* szString, const char* szSubstring)
{
	int nSuperstringLength = (int)strlen(szString);
	int nSubstringLength = (int)strlen(szSubstring);

	for (int nSubstringPos = 0; nSubstringPos <= nSuperstringLength - nSubstringLength; ++nSubstringPos)
	{
		if (strnicmp(szString+nSubstringPos, szSubstring, nSubstringLength) == 0)
			return szString+nSubstringPos;
	}
	return NULL;
}

#include "IScriptSystem.h"
 

#include "Win32specific.h"

#if defined(__GNUC__) && !defined(__SPU__) && !defined(_RELEASE)
#define PRINTF_PARAMS(...) __attribute__ ((format (printf, __VA_ARGS__)))
#define SCANF_PARAMS(...) __attribute__ ((format (scanf, __VA_ARGS__)))
#else
#define PRINTF_PARAMS(...)
#define SCANF_PARAMS(...)
#endif

#if INCLUDE_MEMSTAT_CONTEXTS
#define MEMSTAT_CONTEXT(type, id, str) CMemStatContext _memctx(type, id, str);
#define MEMSTAT_CONTEXT_NAMED(name, type, id, str) CMemStatContext _##name (type, id, str);
#define MEMSTAT_CONTEXT_FMT(type, id, format, ...) CMemStatContext _memctx(type, id, format, __VA_ARGS__);
#define MEMSTAT_CONTEXT_NAMED_FMT(name, type, id, format, ...) CMemStatContext _##name (type, id, format, __VA_ARGS__);
#else
#define MEMSTAT_CONTEXT(...)
#define MEMSTAT_CONTEXT_NAMED(...)
#define MEMSTAT_CONTEXT_FMT(...)
#define MEMSTAT_CONTEXT_NAMED_FMT(...)
#endif

#ifndef VIRTUAL
// VIRTUAL should be used for pure virtual methods with only a single
// implementation - it should be applied to both the method
// declaration/definition in the interface _and_ the implementation (as an
// alternative the 'virtual' keyword may be omitted from the
// implementation).  On platforms not using automatic de-virtualization
// VIRTUAL simply expands to 'virtual'.
#define VIRTUAL virtual
#endif

#ifndef UNIQUE_IFACE
// UNIQUE_IFACE expands to nothing on _all_ platforms, but is recognized by
// the de-virtualization tool.  If placed in front of an interface
// struct/class, all methods are assumed to be unique-virtual.
#define UNIQUE_IFACE
#endif

#define  auto_vector std::vector

// Summary:
//	 System wide events.
enum ESystemEvent
{
	// Description:
	// Seeds all random number generators to the same seed number, WParam will hold seed value.
	//##@{
	ESYSTEM_EVENT_RANDOM_SEED = 1,
	ESYSTEM_EVENT_RANDOM_ENABLE,
	ESYSTEM_EVENT_RANDOM_DISABLE,
	//##@}

	// Description:
	//	 Changes to main window focus.
	//	 wparam is not 0 is focused, 0 if not focused
	ESYSTEM_EVENT_CHANGE_FOCUS = 10,

	// Description:
	//	 Moves of the main window.
	//	 wparam=x, lparam=y
	ESYSTEM_EVENT_MOVE = 11,

	// Description:
	//	 Resizes of the main window.
	//	 wparam=width, lparam=height
	ESYSTEM_EVENT_RESIZE = 12,

	// Description:
	//	 Sent before starting loading a new level.
	//	 Used for a more efficient resource management.
	ESYSTEM_EVENT_LEVEL_LOAD_START,

	// Description:
	//	 Sent after loading a level finished.
	//	 Used for a more efficient resource management.
	ESYSTEM_EVENT_LEVEL_LOAD_END,

	// Description:
	//	 Sent after precaching of the streaming system has been done
	ESYSTEM_EVENT_LEVEL_PRECACHED,

	// Level is unloading.
	ESYSTEM_EVENT_LEVEL_UNLOAD,

	// Summary:
	//	 Sent after level have been unloaded. For cleanup code.
	ESYSTEM_EVENT_LEVEL_POST_UNLOAD,

	// Summary:
	//	 Called when the game framework has been initialized.
	ESYSTEM_EVENT_GAME_POST_INIT,

	// Summary:
	//	 Sent when system is shutting down.
	ESYSTEM_EVENT_SHUTDOWN,

	// Summary:
	//	 When keyboard layout changed.
	ESYSTEM_EVENT_LANGUAGE_CHANGE,

	// Description:
	//	 Toggled fullscreen.
	//	 wparam is 1 means we switched to fullscreen, 0 if for windowed
	ESYSTEM_EVENT_TOGGLE_FULLSCREEN,
	ESYSTEM_EVENT_SHARE_SHADER_COMBINATIONS,

	// Description:
	//	 Sent after precaching of the streaming system has been done
	ESYSTEM_EVENT_LEVEL_PRECACHE_END,

	ESYSTEM_EVENT_LEVEL_LOAD_START_BEGIN,

	ESYSTEM_EVENT_USER = 0x1000,
};

// Description:
//	 Interface used for getting notified when a system event occurs.
struct ISystemEventListener
{
	virtual void OnSystemEvent( ESystemEvent event,UINT_PTR wparam,UINT_PTR lparam ) = 0;
};

#if defined(WIN32) || defined(WIN64) || defined(LINUX)
#	define MAX_WARNING_LENGTH	4096
#else
#	define MAX_WARNING_LENGTH	512
// reduce max warning length for consoles (e.g. to prevent overflows on PS3 where thread stack are rather small)
#endif

static void  CryLogAlways(const char * format, ... )  
{
	if (!format)
		return;

	char buffer[MAX_WARNING_LENGTH];
	va_list args;
	va_start(args, format);
	int count = vsnprintf(buffer, sizeof(buffer),format, args);
	if ( count == -1 || count>= sizeof(buffer) )
		buffer[sizeof(buffer)-1] = '\0';	
	va_end(args);

	OutputDebugStringA((LPCSTR)buffer);
	printf(buffer);
}

static void  CryFatalError(const char *format,... )
{
	if (!format)
		return;

	char buffer[MAX_WARNING_LENGTH];
	va_list args;
	va_start(args, format);
	int count = vsnprintf(buffer, sizeof(buffer),format, args);
	if ( count == -1 || count>= sizeof(buffer) )
		buffer[sizeof(buffer)-1] = '\0';	
	va_end(args);

	OutputDebugStringA((LPCSTR)buffer);
	printf(buffer);
#ifdef _DEBUG
	MessageBoxA(NULL,buffer,"CryFatalError",IDOK);
#endif
	
}

static void ScriptWarning( const char * format, ... )
{
	if (!format) return;

	char buffer[MAX_WARNING_LENGTH];
	va_list args;
	va_start(args, format);
	int count = vsnprintf(buffer, sizeof(buffer),format, args);
	if ( count == -1 || count>= sizeof(buffer) )
		buffer[sizeof(buffer)-1] = '\0';	
	va_end(args);

	OutputDebugStringA((LPCSTR)buffer);
	printf(buffer);
	
}

static void  CryLog( const char * format, ... )
{
	if (!format)
		return;

	char buffer[MAX_WARNING_LENGTH];
	va_list args;
	va_start(args, format);
	int count = vsnprintf(buffer, sizeof(buffer),format, args);
	if ( count == -1 || count>= sizeof(buffer) )
		buffer[sizeof(buffer)-1] = '\0';	
	va_end(args);

	OutputDebugStringA((LPCSTR)buffer);
	printf(buffer);
}

// Description:
//	 Displays warning message.
//	 Logs it to console and file and display a warning message box.
//	 Doesn't terminate execution.
#include "IValidator.h"
void CryWarning(EValidatorModule, EValidatorSeverity, const char *, ...) PRINTF_PARAMS(3, 4);
inline void CryWarning( EValidatorModule module,EValidatorSeverity severity,const char *format,... )
{
	if (!format)
		return;

	char buffer[MAX_WARNING_LENGTH];
	va_list args;
	va_start(args, format);
	int count = vsnprintf(buffer, sizeof(buffer),format, args);
	if ( count == -1 || count>= sizeof(buffer) )
		buffer[sizeof(buffer)-1] = '\0';	
	va_end(args);

	OutputDebugStringA((LPCSTR)buffer);
	printf(buffer);
}

#include "IConsole.h"
// the following macros allow the help text to be easily stripped out
#ifdef EXCLUDE_CVARHELP
#define CVARHELP(_comment)	0
#else
#define CVARHELP(_comment)	_comment
#endif
// Summary:
//	 Preferred way to register a CVar
#define REGISTER_CVAR(_var,_def_val,_flags,_comment)	(CXConsole::GetGlobalInstance() == 0 ? 0 : CXConsole::GetGlobalInstance()->Register((#_var), &(_var), (_def_val), (_flags), CVARHELP(_comment)))
// Summary:
//	 Preferred way to register a string CVar
#define REGISTER_STRING(_name,_def_val,_flags,_comment)	(CXConsole::GetGlobalInstance() == 0 ? 0 : CXConsole::GetGlobalInstance()->RegisterString(_name,(_def_val), (_flags), CVARHELP(_comment)))
// Summary:
//	 Preferred way to register a int CVar
#define REGISTER_INT(_name,_def_val,_flags,_comment)	(CXConsole::GetGlobalInstance() == 0 ? 0 : CXConsole::GetGlobalInstance()->RegisterInt(_name,(_def_val), (_flags), CVARHELP(_comment)))
// Summary:
//	 Preferred way to register a float CVar
#define REGISTER_FLOAT(_name,_def_val,_flags,_comment)	(CXConsole::GetGlobalInstance() == 0 ? 0 : CXConsole::GetGlobalInstance()->RegisterFloat(_name,(_def_val), (_flags), CVARHELP(_comment)))
// Summary:
//	 Offers more flexibility but more code is required
#define REGISTER_CVAR2(_name,_var,_def_val,_flags,_comment)	(CXConsole::GetGlobalInstance() == 0 ? 0 : CXConsole::GetGlobalInstance()->Register(_name, _var, (_def_val), (_flags), CVARHELP(_comment)))
// Summary:
//	 Preferred way to register a console command
#define REGISTER_COMMAND(_name,_func,_flags,_comment)	(CXConsole::GetGlobalInstance() == 0 ? (void)0 : CXConsole::GetGlobalInstance()->AddCommand(_name,_func,(_flags), CVARHELP(_comment)))

#define  CONST_TEMP_STRING string

#define MATH_H <math.h>

#if defined(_MSC_VER)
//#include "MSVCspecific.h"
#define PREFAST_SUPPRESS_WARNING(W) __pragma(warning(suppress:W))
#else
#define PREFAST_SUPPRESS_WARNING(W) 
#endif

#undef IF
#undef WHILE
#define IF(a, b) if((a))
#define WHILE(a, b) while((a))

// Memory manager breaks strdup
// Use something higher level, like CryString
// PS3 headers require this, does not compile otherwise
#if !defined(PS3)
#undef strdup
#define strdup dont_use_strdup
#undef snPause
#define snPause()
#endif

// Define BIT macro for use in enums and bit masks.
#define BIT(x) (1<<(x))

using namespace std;

#include "StlUtils.h"
#include "PublicApi.h"
#include "XConsole.h"
//-----------------------------------------------------------------------------
// particleuniverse
//#include <ParticleUniversePlugin.h>

//-----------------------------------------------------------------------------
// ogitor
//#include <OgitorsEx/Ogitors.h>

//-----------------------------------------------------------------------------
// rapidxml
#include "rapidxml.hpp"
#include "rapidxml_print.hpp"
#include "rapidxml_utils.hpp"
